﻿using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using K9Nano.Dependency;
using K9Nano.Domain;
using Microsoft.Extensions.Logging;

namespace K9Nano.Authorization
{
    public class UserBackListManager : K9DomainServiceBase, IUserBackListManager, IScopedDependency
    {
        public UserBackListManager(IUnitOfWork uow, ILoggerFactory loggerFactory) : base(uow, loggerFactory)
        {
        }

        public IRepository<UserBlacklist, Guid> Repository => Uow.Repository<UserBlacklist, Guid>();

        /// <summary>
        /// 禁止用户登录指定的客户端
        /// </summary>
        /// <param name="userIdOrPhone"></param>
        /// <param name="clients"></param>
        /// <param name="reason"></param>
        /// <param name="cancellation"></param>
        /// <returns></returns>
        public virtual async ValueTask ForbidAsync(string userIdOrPhone, string[] clients, string reason, CancellationToken cancellation)
        {
            var entity = await Repository.FirstOrDefaultAsync(x => x.User == userIdOrPhone, cancellation);
            if (entity != null)
            {
                entity.Reason = reason;
                entity.Policy = EUserBlackListPolicy.Partially;
                if (string.IsNullOrWhiteSpace(entity.Clients))
                {
                    entity.Clients = string.Join(",", clients);
                }
                else
                {
                    entity.Clients = string.Join(",",
                        entity.Clients.Split(',', StringSplitOptions.RemoveEmptyEntries)
                            .Concat(clients)
                            .Distinct());
                }

                await Repository.UpdateAsync(entity, cancellation);
            }
            else
            {
                entity = new UserBlacklist
                {
                    User = userIdOrPhone,
                    Clients = string.Join(",", clients),
                    Reason = reason,
                    Policy = EUserBlackListPolicy.Partially
                };
                await Repository.InsertAsync(entity, cancellation);
            }
        }

        /// <summary>
        /// 禁止用户登录所有客户端
        /// </summary>
        /// <param name="userIdOrPhone"></param>
        /// <param name="reason"></param>
        /// <param name="cancellation"></param>
        /// <returns></returns>
        public virtual async ValueTask ForbidAsync(string userIdOrPhone, string reason, CancellationToken cancellation)
        {
            var entity = await Repository.FirstOrDefaultAsync(x => x.User == userIdOrPhone, cancellation);
            if (entity != null)
            {
                entity.Reason = reason;
                entity.Policy = EUserBlackListPolicy.Entirely;
                entity.Clients = string.Empty;
                await Repository.UpdateAsync(entity, cancellation);
            }
            else
            {
                entity = new UserBlacklist
                {
                    User = userIdOrPhone,
                    Clients = string.Empty,
                    Reason = reason,
                    Policy = EUserBlackListPolicy.Entirely
                };
                await Repository.InsertAsync(entity, cancellation);
            }
        }

        /// <summary>
        /// 禁止用户登录指定的客户端
        /// </summary>
        /// <param name="userIdOrPhone"></param>
        /// <param name="clients"></param>
        /// <param name="cancellation"></param>
        /// <returns></returns>
        public virtual async ValueTask AllowAsync(string userIdOrPhone, string[] clients, CancellationToken cancellation)
        {
            var entity = await Repository.FirstOrDefaultAsync(x => x.User == userIdOrPhone, cancellation);
            if (entity != null)
            {
                if (!string.IsNullOrWhiteSpace(entity.Clients))
                {
                    entity.Clients = string.Join(",",
                        entity.Clients.Split(',', StringSplitOptions.RemoveEmptyEntries)
                            .Where(x => !clients.Contains(x)));
                }

                if (string.IsNullOrWhiteSpace(entity.Clients))
                {
                    await Repository.DeleteAsync(entity, false, cancellation);
                }
                else
                {
                    await Repository.UpdateAsync(entity, cancellation);
                }
            }
        }

        /// <summary>
        /// 允许用户登录所有客户端
        /// </summary>
        /// <param name="userIdOrPhone"></param>
        /// <param name="cancellation"></param>
        /// <returns></returns>
        public virtual async ValueTask AllowAsync(string userIdOrPhone, CancellationToken cancellation)
        {
            await Repository.DeleteAsync(x => x.User == userIdOrPhone, false, 200, cancellation);
        }
    }
}